home *** CD-ROM | disk | FTP | other *** search
/ Shareware Grab Bag / Shareware Grab Bag.iso / 090 / cmln0586.arc / CLIPPER.LTG < prev    next >
Text File  |  1986-04-06  |  6KB  |  172 lines

  1. /*    Line and Polygon Clip Routine - Clipper                */
  2. /*                                       */
  3. /*    This routine is a clipping routine designed to clip lines       */
  4. /*    or polygons.  Parameters are as follows:               */
  5. /*                                       */
  6. /*    points       - Object points to be clipped.               */
  7. /*    num_points - Number of points in object.               */
  8. /*    polygon    - Polygon flag (polygon = 1, line = 0).           */
  9. /*    color       - Color of object.                       */
  10. /*                                       */
  11. struct DTABLE {         /* declare structure for data table       */
  12.   int x;            /* data table x value               */
  13.   int y;            /* data table y value               */
  14.   };
  15.  
  16. #define max( A, B )  ((A) > (B) ? (A) : (B))    /* define a MAX function   */
  17. #define min( A, B )  ((A) < (B) ? (A) : (B))    /* define a MIN function   */
  18.  
  19. Clipper( points, num_points, polygon, color )
  20. struct DTABLE *points;
  21. int num_points;
  22. int polygon;
  23. int color;
  24.  
  25. {
  26. char Outcodes();
  27. char outcode1, outcode2, code;
  28. int done, i, total = 0;
  29. struct DTABLE *pt1, *pt2, *out;     /* coordinate pointers */
  30. struct DTABLE curpt, corner[4];     /* last point; corners of window */
  31.  
  32.   out = (struct DTABLE *)calloc( num_points+8, sizeof(struct DTABLE));
  33.   corner[0].x = XMIN; corner[0].y = YMIN;
  34.   corner[1].x = XMAX; corner[1].y = YMIN;
  35.   corner[2].x = XMIN; corner[2].y = YMAX;
  36.   corner[3].x = XMAX; corner[3].y = YMAX;
  37.   pt1 = points;
  38.   for ( i = 1; i<num_points; ++i ) {
  39.     done = 0;
  40.     pt2 = points+i;
  41.     curpt.x = pt2->x; curpt.y = pt2->y;        /* SAVE CURRENT POINT */
  42.     do {
  43.       outcode1 = Outcodes( pt1 );
  44.       outcode2 = Outcodes( pt2 );
  45.       if (outcode1 & outcode2) {           /* REJECT POINTS */
  46.      if (polygon) {
  47.        code = Save_Corner(pt1, outcode1);
  48.        if (code) total = Put_Point( &corner[code/3-1], out, total );
  49.      } else {
  50.         if (total > 1) polyline( color, out, total);
  51.         total = 0;
  52.      };
  53.      done = 1;
  54.       }
  55.       else if ((!outcode1) && (!outcode2)) {         /* ACCEPT POINTS */
  56.            total = Put_Point( pt1, out, total );
  57.            total = Put_Point( pt2, out, total );
  58.            done = 1;
  59.       }
  60.       else if (!outcode1) {         /* point 1 inside; point 2 outside */
  61.           Clip( pt2, pt1, outcode2 );
  62.       }
  63.       else if (!outcode2) {         /* point 2 inside; point 1 outside */
  64.      if (polygon) {
  65.         code = Save_Corner(pt1, outcode1);
  66.         if (code) total = Put_Point( &corner[code/3-1], out, total );
  67.      } else {
  68.         if (total > 1) polyline( color, out, total);
  69.         total = 0;
  70.      };
  71.      Clip( pt1, pt2, outcode1 );
  72.       }
  73.       else {              /* both points outside; different sides */
  74.      if (polygon) {
  75.         code = Save_Corner(pt1, outcode1);
  76.         if (code) total = Put_Point( &corner[code/3-1], out, total );
  77.      } else {
  78.         if (total > 1) polyline( color, out, total);
  79.         total = 0;
  80.      };
  81.      Clip( pt1, pt2, outcode1 );
  82.       }
  83.     } while (!done);
  84.     pt1->x = curpt.x; pt1->y = curpt.y;
  85.   }    /* end for loop */
  86.  
  87.   if (polygon) {     /* first point must equal last */
  88.      if((out[0].x != out[total].x) && (out[0].y != out[total].y))
  89.     total = Put_Point( &out[0], out, total );
  90.      polyhatch( color, out, total );
  91.   }  else if (total > 1) polyline( color, out, total);
  92.   free(out);
  93. }
  94.  
  95. int Clip( pt1, pt2, code )
  96. struct DTABLE *pt1, *pt2;
  97. char code;
  98.  
  99. {
  100.    if (code & 0x08) {         /* CLIP TOP */
  101.       pt1->x += (pt2->x-pt1->x) * (YMAX-pt1->y) / (pt2->y-pt1->y);
  102.       pt1->y = YMAX;
  103.    } else if (code & 0x02) {     /* CLIP BOTTOM */
  104.       pt1->x += (pt2->x-pt1->x) * (YMIN-pt1->y) / (pt2->y-pt1->y);
  105.       pt1->y = YMIN;
  106.    } else if (code & 0x04) {     /* CLIP RIGHT */
  107.       pt1->y += (pt2->y-pt1->y) * (XMAX-pt1->x) / (pt2->x-pt1->x);
  108.       pt1->x = XMAX;
  109.    } else if (code & 0x01) {     /* CLIP LEFT */
  110.       pt1->y += (pt2->y-pt1->y) * (XMIN-pt1->x) / (pt2->x-pt1->x);
  111.       pt1->x = XMIN;
  112.    };
  113. }
  114.  
  115. char Outcodes( pt )
  116. struct DTABLE *pt;
  117.  
  118. {
  119. char code = 0x00;
  120.  
  121.    if (pt->x < XMIN) code |= 0x01;    /* Left Side   */
  122.    if (pt->x > XMAX) code |= 0x04;    /* Right Side  */
  123.    if (pt->y < YMIN) code |= 0x02;    /* Bottom Side */
  124.    if (pt->y > YMAX) code |= 0x08;    /* Top Side    */
  125.    return ( code );
  126. }
  127.  
  128.  
  129. int Save_Corner( pt, code )
  130. struct DTABLE *pt;
  131. char code;
  132.  
  133. {
  134.    if (pt->x == XMIN) return(code|0x01);  /* Bottom Boundary    */
  135.    if (pt->x == XMAX) return(code|0x04);  /* Top Boundary    */
  136.    if (pt->y == YMIN) return(code|0x02);  /* Left Boundary    */
  137.    if (pt->y == YMAX) return(code|0x08);  /* Right Boundary    */
  138.    if (!(code%3))     return(code);      /* Point is in corner */
  139.    return(0);                  /* Don't save corner  */
  140. }
  141.  
  142. int Put_Point( pt, out, num )
  143. struct DTABLE  *pt, *out;
  144. int num;
  145.  
  146. {
  147. float m1,m2;        /* slopes of two pairs of points  */
  148. float dx1,dx2;        /* delta x of two pairs of points */
  149.  
  150.    if (!num) {                 /* FIRST POINT TO BE ENTERED */
  151.       out[num].x = pt->x; out[num].y = pt->y;    return( num+1 );
  152.    }
  153.    if (num)                 /* NEW POINT = LAST POINT? */
  154.       if ((pt->x == out[num-1].x) && (pt->y == out[num-1].y)) return(num);
  155.    if (num == 1) {             /* NO COLINEAR POINTS YET */
  156.       out[num].x = pt->x; out[num].y = pt->y; return( num+1 );
  157.    }
  158.    dx1 = (float)(out[num-1].x - out[num-2].x);
  159.    dx2 = (float)(pt->x - out[num-2].x);
  160.    if ((dx1 == 0.0) && ( dx2 == 0.0)) {       /* VERTICAL SLOPES */
  161.       out[num-1].x = pt->x; out[num-1].y = pt->y; return(num);
  162.    }
  163.    if ((int)dx1 && (int)dx2) {
  164.       m1 = (float)(out[num-1].y - out[num-2].y) / dx1;
  165.       m2 = (float)(pt->y - out[num-2].y) / dx2;
  166.       if ( m1 == m2 ) {               /* REMOVE COLINEAR POINTS */
  167.      out[num-1].x = pt->x; out[num-1].y = pt->y; return(num);
  168.       }
  169.    }
  170.    out[num].x = pt->x; out[num].y = pt->y; return( num+1 );
  171. }
  172.